/***************************************************************************************************
  *Copyright(C),2010-2016,Sumscope
  *FileName	:  proto_message.cpp
  *Author	:  scofined.qi
  *Version	:  1.0
  *Date		:  2019/01/18
  *Desc		:  //用于主要说明此程序文件完成的主要功能
  *Relation :
  *Others	:  //其他内容说明
  *Function :  //主要函数列表，每条记录应包含函数名及功能简要说明
  *History	:  //修改历史记录列表，每条修改记录应包含修改日期、修改者及修改内容简介
  ***************************************************************************************************/
#include "include/proto_message.h"
#include "include/JsonWriter.h"
#include <algorithm>

#include "core/thirdparty/zlib/zlib.h"
#ifndef SSBASE_STATIC

#ifdef _DEBUG
#pragma comment(lib,"zlibd.lib")
#pragma comment(lib,"zlibstaticd.lib")
#else
#pragma comment(lib,"zlib.lib")
#pragma comment(lib,"zlibstatic.lib")
#endif
#endif

#define FIELD_OFFSET2(type, field)    ((long)(long long*)&(((type *)0)->field))
#define RTL_FIELD_SIZE2(type, field) (sizeof(((type *)0)->field))

namespace qb{
	namespace base{
		namespace msg{
#define Y_RD_SERVICE_MESSAGE_BLOCK_LEN 2048*20
			bool bUnZip(char *in, int in_len, char *out, int *out_len)
			{
				z_stream strm;
				int ret;

				strm.zalloc = Z_NULL;
				strm.zfree = Z_NULL;
				strm.opaque = Z_NULL;
				strm.avail_in = 0;
				strm.next_in = Z_NULL;
			//	try
				{
					ret = inflateInit(&strm);
					if (ret != Z_OK)
					{
						return false;
					}
					strm.avail_in = in_len;
					strm.next_in = (Bytef *)in;
					strm.avail_out = Y_RD_SERVICE_MESSAGE_BLOCK_LEN;
					strm.next_out = (Bytef *)out;
					ret = inflate(&strm, Z_FINISH);
					if (ret == Z_DATA_ERROR || ret == Z_NEED_DICT || ret == Z_MEM_ERROR)
					{
						inflateEnd(&strm);
						return false;
					}
					else
					{
						*out_len = Y_RD_SERVICE_MESSAGE_BLOCK_LEN - strm.avail_out;
						inflateEnd(&strm);
						return true;
					}
				}
			//	catch (...)
				{
			//		inflateEnd(&strm);
			//		return false;
				}
			}


			static const std::string PropType = "Type.Prop";
			static const std::string PropSubject = "Subject.Prop";
			static const std::string PropMessageID = "MessageID.Prop";
			bool IsCheckProtoMessageEnable(){
				static bool init = false;
				static bool enable = false;
				if (!init){
					init = true;
				//	enable = cfg::GetConfigBool(kBaseConfigCheckProtoMessage); //syy
				}
				return enable;
			}

#define MSGASSERT(smt)	if(IsCheckProtoMessageEnable()){(void)( (!!(smt)) || (qb::base::DbgError(#smt,__FILE__,__FUNCTION__,__LINE__,""), 0) );}
#define MSGCHECKTYPE()	if(IsCheckProtoMessageEnable()){BASSERTS(false, "NAME(%s)'s type is not expected:VAR_STRING  real:%d", name, v.Type);}

			enum kType : unsigned char{
				//注意,此字段必须与proto库的bool Decoder::Decode(Variant& var)里面的值保持一致
				kTypeInvalid = 0,
				kTypeBool = 0x08,
				kTypeInt8 = 0x02,
				kTypeUInt8 = 0x03,
				kTypeInt16 = 0x11,
				kTypeUInt16 = 0x12,
				kTypeInt32 = 0x21,
				kTypeUInt32 = 0x22,
				kTypeInt64 = 0x31,
				kTypeUInt64 = 0x32,

				kTypeFloat = 0x23,
				kTypeDouble = 0x33,

				kTypeString = 0x95,
				kTypeRaw1 = 0x80,
				kTypeRaw2 = 0x90,
				kTypeRaw4 = 0xa0,
				kTypeMap = 0xa8,
				kTypeList = 0xa9,
				kTypeVoid = 0xf0,
			};

			namespace{
				struct DecodeData{
					union{
						bool	b;
						int8_t  i8;
						uint8_t u8;
						int16_t i16;
						uint16_t u16;
						int32_t i32;
						uint32_t u32;
						float	f;
						int64_t i64;
						uint64_t u64;
						double	d;
					}u;
				};

				template<int N>
				DecodeData DecodeValue(const char* data)
				{
					DecodeData dd;
					dd.u.u8 = *((const uint8_t*)data);
					return dd;
				}
				template<> DecodeData DecodeValue<2>(const char* data)
				{
					DecodeData dd;
					dd.u.u16 = (((uint8_t)data[0]) << 8) | ((uint8_t)data[1]);
					return dd;
				}
				template<> DecodeData DecodeValue<4>(const char* data)
				{
					DecodeData dd;
					uint32_t a = (uint8_t)data[0];
					uint32_t b = (uint8_t)data[1];
					uint32_t c = (uint8_t)data[2];
					uint32_t d = (uint8_t)data[3];
					dd.u.u32 = (a << 24) | (b << 16) | (c << 8) | d;
					return dd;
				}
				template<> DecodeData DecodeValue<8>(const char* data)
				{
					uint64_t hi = DecodeValue<4>(data).u.u32;
					uint64_t lo = DecodeValue<4>(data + 4).u.u32;
					DecodeData dd;
					dd.u.u64 = (hi << 32) | lo;
					return dd;
				}

				template<class T>
				inline T DecodeOneValue(const char* data, const char* end, const T& fail)
				{
					if (data + sizeof(T) > end)return fail;
					DecodeData dd = DecodeValue<sizeof(T)>(data);
					return *((const T*)&dd);
				}

#define DECODE_TYPE(TYPE,FAIL)	DecodeOneValue(decode,end,(TYPE)(FAIL))
#define DECODE_DATA(DATA,TYPE)	DecodeOneValue(DATA,DATA+sizeof(TYPE),TYPE(0))


			}
			ValueDict::ValueDict() :m_buffer(nullptr), m_capcity(1024)
			{

			}

			ValueDict::~ValueDict()
			{
				if (m_buffer)
					delete[] m_buffer;
				m_buffer = nullptr;
			}

			bool ValueDict::Parse(const char* data, int len)
			{
				if (data == nullptr || len <= 0)
					return false;

				if (m_buffer == nullptr || m_capcity < Y_RD_SERVICE_MESSAGE_BLOCK_LEN)
				{
					if (m_buffer)delete[] m_buffer;
					m_capcity = Y_RD_SERVICE_MESSAGE_BLOCK_LEN;
					m_buffer = new char[m_capcity];
					memset(m_buffer, 0, m_capcity);
				}

				int size = 0;
				if (!bUnZip((char*)data, len, m_buffer, &size))
					return false;

				char* buf = m_buffer;
				PackHeader head = *((PackHeader*)buf);
				std::vector<const char*> fields; fields.reserve(head.FieldCount);
				int pack_headsize = FIELD_OFFSET2(PackHeader, FieldCount) + RTL_FIELD_SIZE2(PackHeader, FieldCount);
				const char* field_start = buf + pack_headsize;
				if (size <= pack_headsize)
					return false;
				if (head.tag != 0x53524244)
					return false;
				if (head.FieldCount > 1000)
					return false;
				for (int i = 0; i < head.FieldCount; i++)
				{
					fields.push_back(field_start);
					field_start += strlen(field_start) + 2;
				}
				int nfield = fields.size();
				const char* record_start = buf + head.StartPos + 8;
				if (record_start - buf >= size)
					return false;
				int typelens[kPackDateTypeCount] = { 0, 0, 0, 0, 0,
					sizeof(int), 0, 0, 0, 0,
					1, 0, sizeof(double), 0, sizeof(time_t), 0
				};// 各个类型的数据长度,参见_SkipBuffer
				if (!IsValidDict(head, record_start, nfield))
					return false;
				m_packsize = size;
				m_head = head;
				m_fields = fields;
				m_values.reserve(head.RecordCount*head.FieldCount);
				m_values.clear();
				time_t t = 0;
				Field val = { kPackDateTypeNone, 0, 0, 0, nullptr, nullptr };
				for (int i = 0; i < (int)head.RecordCount; i++)
				{
					const char* record = record_start;
					int ignore_col_count = 0;
					val.row = i;
					for (int j = 0; j < (int)head.FieldCount; j++)
					{
						val.col = j;
						val.type = kPackDateTypeNone;
						val.name = m_fields[j];
						val.data = nullptr;// 默认值
						kPackDateType type = (kPackDateType)(*record);
						char gap = record[1];//类型之后的一个字节
						const char* data = record + 2;	// 变长的数据开始,长度由类型和内容决定
						if (gap != 0)
						{
							record = record + 2;
							ignore_col_count++;
							m_values.push_back(val);
							continue;
						}
						int len = 2 + typelens[type];
						int dlen = (type == kPackDateTypeString) ? strlen(data) : 0;
						len += dlen;
						if (j >= nfield)	// 此字段QB没有,忽略
						{
							record = record + len;
							m_values.push_back(val);
							continue;
						}
						val.type = type;
						val.data = data;
						switch (type)
						{
						case kPackDateTypeInt32:val.len = sizeof(int); break;
						case kPackDateTypeTime32:val.len = sizeof(time_t); break;
						case kPackDateTypeDouble:val.len = sizeof(double); break;
						case kPackDateTypeString:val.len = dlen; break;
						default:break;
						}
						record = record + len;
						m_values.push_back(val);
					}
					record_start = record + 8;//两条记录之间间隔8字节
				}
				if (m_values.size() != m_head.RecordCount*m_head.FieldCount)
					return false;
				return true;
			}

			bool ValueDict::GetValue(int row, int col, Field& value) const
			{
				int index = row*m_head.FieldCount + col;
				if (index >= 0 && index < m_values.size())
				{
					value = m_values[index];
					return true;
				}
				return false;
			}

			const char* ValueDict::GetColName(int col) const
			{
				if (col >= 0 && col < m_fields.size())
					return m_fields[col];
				return nullptr;
			}

			bool ValueDict::IsValidDict(const PackHeader& head, const char* start, int nfield)
			{
				int typelens[kPackDateTypeCount] = { 0, 0, 0, 0, 0,
					sizeof(int), 0, 0, 0, 0,
					1, 0, sizeof(double), 0, sizeof(time_t), 0
				};// 各个类型的数据长度,参见_SkipBuffer
				const char* record_start = start;
				for (int i = 0; i < (int)head.RecordCount; i++)
				{
					const char* record = record_start;
					int ignore_col_count = 0;
					for (int j = 0; j < (int)head.FieldCount; j++)
					{
						kPackDateType type = (kPackDateType)(*record);
						char gap = record[1];//类型之后的一个字节
						const char* data = record + 2;	// 变长的数据开始,长度由类型和内容决定
						if (gap != 0)
						{
							//LOGWARN("ignore col:%d", j);
							record = record + 2;
							ignore_col_count++;
							continue;
						}
						int len = 2 + typelens[type];
						int dlen = (type == kPackDateTypeString) ? strlen(data) : 0;
						len += dlen;
						if (j >= nfield)	// 此字段QB没有,忽略
						{
							record = record + len;
							continue;
						}
						switch (type)
						{
						case kPackDateTypeInt32:
						case kPackDateTypeTime32:
						case kPackDateTypeDouble:
						case kPackDateTypeString:
							break;
						default:
							return false; break;
						}
						record = record + len;
					}
					record_start = record + 8;//两条记录之间间隔8字节
				}
				return true;
			}

			std::string Value::tostring()const
			{
				class ValueFormater{
					char		buffer[256];
				public:
					ValueFormater(VarType t, const char* d, int s){
						switch (t)
						{
						case Value::VAR_BOOL:sprintf(buffer, "bool:%s", *((bool*)d) ? "true" : "false"); break;
						case Value::VAR_INT8:sprintf(buffer, "INT8:%c", *((int8_t*)d)); break;
						case Value::VAR_UINT8:sprintf(buffer, "UINT8:%c", *((uint8_t*)d)); break;
						case Value::VAR_INT16:sprintf(buffer, "INT16:%d", DECODE_DATA(d, int16_t)); break;
						case Value::VAR_UINT16:sprintf(buffer, "UINT16:%d", DECODE_DATA(d, uint16_t)); break;
						case Value::VAR_INT32:sprintf(buffer, "INT32:%d", DECODE_DATA(d, int32_t)); break;
						case Value::VAR_UINT32:sprintf(buffer, "UINT32:%d", DECODE_DATA(d, uint32_t)); break;
						case Value::VAR_INT64:sprintf(buffer, "INT64:%lld", DECODE_DATA(d, int64_t)); break;
						case Value::VAR_UINT64:sprintf(buffer, "UINT64:%lld", DECODE_DATA(d, uint64_t)); break;
						case Value::VAR_FLOAT:sprintf(buffer, "float:%f", DECODE_DATA(d, float)); break;
						case Value::VAR_DOUBLE:sprintf(buffer, "double:%f", DECODE_DATA(d, double)); break;
						case Value::VAR_VOID:sprintf(buffer, "void: "); break;
						case Value::VAR_RAW:sprintf(buffer, "raw:%d", s); break;
						case Value::VAR_STRING:sprintf(buffer, "string:%s", std::string(d, s).c_str()); break;
						default:sprintf(buffer, "unknown:%d", s); break;
							break;
						}
					}
					const char* c_str()const{ return buffer; }
				};

				ValueFormater fmt((VarType)Type, data, size);
				if (key)
				{
					char buf[1024] = { 0 };
					sprintf(buf, "%24s:%s", std::string(key, keylen).c_str(), fmt.c_str());
					return buf;
				}
				return fmt.c_str();
			}

			std::string Value::GetString() const
			{
				if (Type == Value::VAR_STRING && data)return std::string(data, size);
				return "";
			}

			bool Value::GetInt32(int& value) const
			{
				if (Type == Value::VAR_INT32) {
					value = operator int();
					return true;
				}
				return false;
			}

			bool Value::GetDouble(double& value) const
			{
				if (Type == Value::VAR_DOUBLE) {
					value = operator double();
					return true;
				}
				return false;
			}

			bool Value::RefString(const char *& value, size_t &size) const
			{
				if (Type == Value::VAR_STRING)
				{
					value = this->data;
					size = this->size;
					return true;
				}
				return false;
			}



#define IMPL_OPERATOR(TYPE) Value::operator TYPE()const{DecodeData dd = DecodeValue<sizeof(TYPE)>(data);return *((const TYPE*)&dd); }

			IMPL_OPERATOR(bool);
			IMPL_OPERATOR(uint8_t);
			IMPL_OPERATOR(uint16_t);
			IMPL_OPERATOR(uint32_t);
			IMPL_OPERATOR(uint64_t);
			IMPL_OPERATOR(int8_t);
			IMPL_OPERATOR(int16_t);
			IMPL_OPERATOR(int32_t);
			IMPL_OPERATOR(int64_t);
			IMPL_OPERATOR(float);
			IMPL_OPERATOR(double);

			/////////////////////////////////////////////////////////////////////////////
			const ValueList::const_iterator& ValueList::const_iterator::operator++()
			{
				Value nextv;
				Buffer buf(m_value.next(), m_scope.end() - m_value.next(), m_scope.count);
				if (Message::DecodeValue(buf, m_value.ptype == Value::VAR_MAP, nextv))
				{
					nextv.level = m_value.level;
					nextv.msg = m_value.msg;
					nextv.ptype = m_value.ptype;
					nextv.parent = m_value.parent;
					m_value = nextv;
					m_index++;
				}
				else
				{
					m_scope = Buffer();
					m_value = Value();
					m_index = -1;
				}
				return *this;
			}

			ValueList::const_iterator ValueList::begin() const
			{
				Value subvalue;
				Buffer buf(m_value.data, m_value.size, m_value.count);
				if (Message::DecodeValue(buf, m_value.Type == Value::VAR_MAP, subvalue))
				{
					subvalue.level = m_value.level + 1;
					subvalue.msg = m_value.msg;
					subvalue.ptype = m_value.Type;
					subvalue.parent = buf;
					return const_iterator(buf, subvalue, 0);
				}
				return m_end;
			}

			bool ValueMap::find(const char* name, Value& v)const
			{
				if (m_value.msg == nullptr)
					return false;
				return m_value.msg->find(name, *this, v);
			}

			bool ValueMap::GetString(const char* name, const char*& value, size_t& size) const
			{
				Value v;
				if (find(name, v))
				{
					if (v.Type == Value::VAR_STRING)
					{
						value = v.data; size = v.size;
						return true;
					}
				}
				return false;
			}

			bool ValueMap::GetMap(const char* name, ValueMap& vmap) const
			{
				Value v;
				if (find(name, v))
				{
					if (v.Type == Value::VAR_MAP){ vmap = v; return true; }
				}
				return false;
			}

			bool ValueMap::GetList(const char* name, ValueList& vlist) const
			{
				Value v;
				if (find(name, v))
				{
					if (v.Type == Value::VAR_LIST){ vlist = v; return true; }
				}
				return false;
			}

			bool ValueMap::GetRaw(const char *name, Raw& value) const
			{
				Value v;
				if (find(name, v))
				{
					if (v.Type == Value::VAR_RAW){
						value = Raw(v.data, v.size);
						return true;
					}
				}
				return false;
			}

			Message::Message() :m_bfind(0), m_sfind(0){}
			Message::~Message()
			{

			}
			void Message::Clear()
			{
				//if (m_bfind > m_sfind)
				//{
				//	int bytes = m_header.value().bytes + m_map.value().bytes;
				//	const char* value = nullptr;
				//	size_t size = 0;
				//	m_header.GetString(PropType.c_str(), value, size);
				//	BLOGINFO("[MESSAGE][FIND]funcid:%s  bfind:%6d  sfind:%6d  length:%8d", 
				//		value ? string(value,size).c_str() : "", m_bfind, m_sfind, bytes);
				//}
				Value v;
				m_header = v;
				m_map = v;
				m_bfind = 0;
				m_sfind = 0;
			}
			int Message::decodeMap(const char* buf, int len, bool inMap)
			{
				// 只解析Map,忽略头部
				Value v;
				m_header = v;
				if (!DecodeValue(Buffer(buf, len), inMap, v, false))
				{
					return -1;
				}	
				v.msg = this;
				m_map = v;
				return v.bytes;
			}
			int Message::decode(const char* buf, int len)
			{
				// Message包含2个map,第一个是头部,第二个是body
				// 两个map都没有type字段和key,因此要忽略
				Value v;
				if (!DecodeValue(Buffer(buf, len), false, v, true))
				{
					return -1;
				}
				v.parent = Buffer(buf, len);
				v.msg = this;
				m_header = v;
				if (!DecodeValue(Buffer(buf + v.bytes, len - v.bytes), false, v, true))
				{
					return -1;
				}
				v.parent = Buffer(buf + v.bytes, len - v.bytes);
				v.msg = this;
				m_map = v;
				
				return m_header.value().bytes + v.bytes;
			}

			bool Message::DecodeValue(const Buffer& buf, bool inMap, Value& value, bool skipType)
			{
				// 5个编码:KEY	TYPE	SIZE	COUNT	CONTENT
				// SIZE:只有list,map才有,指的是COUNT和CONTENT共同占据的大小
				const char* data = buf.data;

				int length = buf.size;
				if (data == nullptr || length < 1)return false;
				const char* end = data + length;
				const char* decode = data;

				//KEY
				Value v;
				if (inMap)
				{

					v.keylen = DECODE_TYPE(uint8_t, 0);		// 只支持最长256的key
					decode += sizeof(uint8_t);
					v.key = decode;
					decode += v.keylen;
					if (decode >= end)
					{
						return false;
					}
				}
				else
				{
					v.key = nullptr;
					v.keylen = 0;
				}
				//TYPE
				kType type = kTypeInvalid;
				if (skipType)
				{
					type = kTypeMap;
				}
				else
				{
					type = DECODE_TYPE(kType, kTypeInvalid);
					decode += sizeof(uint8_t);
				}

				if (type == kTypeInvalid)
				{
					return false;
				}

				//SIZE,COUNT,TYPE
				v.count = 0;
				switch (type)
				{
				case kTypeBool:v.size = sizeof(bool); v.Type = Value::VAR_BOOL; break;
				case kTypeInt8:v.size = sizeof(int8_t); v.Type = Value::VAR_INT8; break;
				case kTypeUInt8:v.size = sizeof(uint8_t); v.Type = Value::VAR_UINT8; break;
				case kTypeInt16:v.size = sizeof(int16_t); v.Type = Value::VAR_INT16; break;
				case kTypeUInt16:v.size = sizeof(uint16_t); v.Type = Value::VAR_UINT16; break;
				case kTypeInt32:v.size = sizeof(int32_t); v.Type = Value::VAR_INT32; break;
				case kTypeUInt32:v.size = sizeof(uint32_t); v.Type = Value::VAR_UINT32; break;
				case kTypeInt64:v.size = sizeof(int64_t); v.Type = Value::VAR_INT64; break;
				case kTypeUInt64:v.size = sizeof(uint64_t); v.Type = Value::VAR_UINT64; break;
				case kTypeFloat:v.size = sizeof(float); v.Type = Value::VAR_FLOAT; break;
				case kTypeDouble:v.size = sizeof(double); v.Type = Value::VAR_DOUBLE; break;
				case kTypeString:
					v.size = DECODE_TYPE(uint16_t, -1);//see Encoder::EncodeString
					v.Type = Value::VAR_STRING;
					decode += sizeof(uint16_t);
					break;
				case kTypeRaw1:
					v.size = DECODE_TYPE(uint8_t, -1);//see Encoder::EncodeRaw
					v.Type = Value::VAR_RAW;
					decode += sizeof(uint8_t);
					break;
				case kTypeRaw2:
					v.size = DECODE_TYPE(uint16_t, -1);
					v.Type = Value::VAR_RAW;
					decode += sizeof(uint16_t);
					break;
				case kTypeRaw4:
					v.size = DECODE_TYPE(uint32_t, -1);
					v.Type = Value::VAR_RAW;
					decode += sizeof(uint32_t);
					break;
				case kTypeList:
				case kTypeMap:
					v.Type = (type == kTypeList) ? Value::VAR_LIST : Value::VAR_MAP;
					v.size = DECODE_TYPE(uint32_t, -1);
					decode += sizeof(uint32_t);
					v.count = DECODE_TYPE(uint32_t, -1);
					decode += sizeof(uint32_t);
					v.size -= sizeof(uint32_t);//参考Encoder::EncodeMap中的size-5
					break;
				default:
					return false;
				}
				//CONTENT
				v.bytes = v.size + (decode - data);
				v.data = decode;
				if (v.size < 0 || v.count<0 || decode>end || decode + v.size>end || v.bytes <= 0)
				{
					return false;
				}
				value = v;
				return true;
			}

			bool Message::find(const char* name, const ValueMap& map, Value& v)
			{
				// 当m_field_table没有与map绑定的时候,需要立即重建
				Buffer buf(map.value().data, map.value().size);
				if (m_field_table.buffer() != buf)
				{
					m_field_table.rebuild(map);
				}
				FieldTable::kFindType type=m_field_table.getFieldValue(name, strlen(name), v);
				//m_bfind += (type == FieldTable::kFindTypeByBinary) ? 1 : 0;
				//m_sfind += (type == FieldTable::kFindTypeByOrder) ? 1 : 0;
				return type != FieldTable::kFindTypeFail;
			}

			//////////////////////////////////////////////////////////////////////////
			namespace{
				bool CheckNotExist(const Value* arr, int nsize, const char* name, int len)
				{
					int index = -1;
					for (int i = 0; i < nsize; i++)
					{
						const Value& val = arr[i];
						int cmp = FieldTable::CompString(name, len, val.key, val.keylen);
						if (cmp == 0)
							return false;
					}
					return true;
				}
				bool CheckSorted(const Value* arr, int nsize)
				{
					if (nsize <= 1)return true;
					for (int i = 1; i < nsize; i++)
					{
						int cmp = FieldTable::CompByKey(&arr[i - 1], &arr[i]);
						if (cmp > 0)
							return false;
					}
					return true;
				}

			}
			FieldTable::FieldTable() :m_lastpos(0){}
			void FieldTable::rebuild(const ValueMap& map)
			{
				m_lastpos = 0;
				m_signature = Buffer(map.value().data, map.value().size);
				m_values.Reset();

				for (ValueList::const_iterator it = map.begin(); it != map.end(); ++it)
				{
					const Value& v = *it;
					m_values.Add(v);
				}

				//if (0)
				//{
				//	// 实际找到的最大值是32,因此64是足够的
				//	static int maxSize = 0;
				//	if (maxSize < map.size())
				//	{
				//		maxSize = map.size();
				//		string names;
				//		for (int i = 0; i < m_values.size(); i++)
				//			names += string(m_values[i].key, m_values[i].keylen) + string(",");
				//		BLOGINFO("[MESSAGE]max:%6d names:%s", maxSize, names.c_str());
				//	}
				//}

				// 确保m_values的数据是有序的
				if (m_values.size() > 1)
				{
					qsort(m_values.GetBuf(), m_values.size(), sizeof(Value), FieldTable::CompByKey);
				}
			}
			int FieldTable::CompString(const char* s1, int len1, const char* s2, int len2)
			{
				if (s1 && s2)
				{
					// 实测 如下代码比strncmp好太多太多!!!
					int len = len1 < len2 ? len1 : len2;
					int cmp = 0;
					for (int i = 0; i < len; i++)
					{
						if (s1[i] != s2[i])
						{
							cmp = s1[i] < s2[i] ? (-1) : 1;
							break;
						}
					}
					return cmp != 0 ? cmp : (len1 == len2 ? 0 : (len1 < len2 ? (-1) : 1));
				}
				return s1 == s2 ? 0 : (!s1 ? (-1) : 1);
			}
			int FieldTable::CompByKey(const void * p1, const void * p2)
			{
				const Value* v1 = (const Value*)p1;
				const Value* v2 = (const Value*)p2;
				return CompString(v1->key, v1->keylen, v2->key, v2->keylen);
			}

			namespace{

				int find_last(const FieldTable::ValueArray& values, int pos, const char* name, int len)
				{
					// 从pos往两边找,如果发现有名称与pos相同,继续找,直到找到最后一个与pos名称相同的为止
					// 原因在于:服务器后台可能在一个map下面,放置多个相同名称的值,取最后一个
					// 如果直接返回pos,那么忽略相同key的情况
					if (1)
					{
						int nsize = values.size();
						for (int k = pos + 1; k < nsize; ++k)
						{
							const Value& val = values[k];
							if (FieldTable::CompString(name, len, val.key, val.keylen) != 0)
								break;
							if (val.data>values[pos].data)
								pos = k;
						}
						for (int k = pos -1; k >=0; --k)
						{
							const Value& val = values[k];
							if (FieldTable::CompString(name, len, val.key, val.keylen) != 0)
								break;
							if (val.data > values[pos].data)
								pos = k;
						}
					}
					return pos;
				}
			}
			FieldTable::kFindType FieldTable::getFieldValue(const char* name, int len, Value& v) const
			{
				// 首先尝试上一次的位置开始搜索,2-3个位置
				// 再次使用二分法搜索
				// 利用cmp和pos,还可以进一步缩减bsearch的范围
				// 注意,原始服务器代码中,同一个map下面,可能存在若干个同名的value
				// 由于已经排序过
				if (m_values.size() <= 0)return kFindTypeFail;
				int start = m_lastpos == 0 ? (-1) : m_lastpos;
				int nsize = m_values.size();
				if (nsize <= 0)
					return kFindTypeFail;
				int cmp = 0, pos = 0, nmax = 3 < nsize ? 3 : nsize;
				for (int i = 0; i < nmax; i++)
				{
					pos = (i + start + 1) % nsize;
					const Value& val = m_values[pos];
					cmp = CompString(name, len, val.key, val.keylen);
					if (cmp == 0)
					{
						pos = find_last(m_values, pos, name, len);
						v = m_values[pos];
						(const_cast<FieldTable*>(this))->m_lastpos = pos;
						return kFindTypeByOrder;
					}
					else if (cmp < 0)
					{
						int last = pos - 1;
						cmp = last<0?(1):(CompString(name, len, m_values[last].key, m_values[last].keylen));
						if (cmp == 0)
						{
							pos = find_last(m_values, last, name, len);
							v = m_values[pos];
							(const_cast<FieldTable*>(this))->m_lastpos = pos;
							return kFindTypeByOrder;
						}
						if (cmp > 0)
						{
							return kFindTypeFail;
						}
						break;
					}
				}
				(const_cast<FieldTable*>(this))->m_search.key = name;
				(const_cast<FieldTable*>(this))->m_search.keylen = len;

				const Value* arr = m_values;
				const Value* ret = nullptr;
				if (cmp < 0)
				{
					ret=(const Value*)bsearch(&m_search, arr, pos, sizeof(Value), FieldTable::CompByKey);
				}
				else
				{
					ret=(const Value*)bsearch(&m_search, arr+pos+1, nsize-pos-1, sizeof(Value), FieldTable::CompByKey);
				}
				if (ret)
				{
					pos = ret - arr;
					pos = find_last(m_values, pos, name, len);
					v = m_values[pos];
					(const_cast<FieldTable*>(this))->m_lastpos = pos;

					return kFindTypeByBinary;
				}

				return kFindTypeFail;
			}
			bool FieldTable::getFieldValue(int index, Value& v) const
			{
				if (index < 0 || index >= m_values.size())
					return false;
				v = m_values.at(index);
				return true;
			}

			/////////////////////////////////////////////////////////////////////////////
			bool ProtoMap::RefList(const char* name, const ProtoList*& pList)const
			{
				pList = nullptr;
				ValueList v;
				if (m_map.GetList(name, v))
				{
					ProtoList* list = new ProtoList(v);
					(const_cast<ProtoMap*>(this))->m_reflist.push_back(list);
					pList = list;
					return true;
				}
				return false;
			}

			bool ProtoMap::RefMapFrom(const Message& msg, const char* name)
			{
				return msg.MapValue().GetMap(name, m_map);
			}

			bool ProtoMap::GetList(const char* name, ProtoList& list) const
			{
				ValueList vlist;
				if (m_map.GetList(name, vlist))
				{
					list.SetList(vlist);
					return true;
				}
				return false;
			}

			bool ProtoMap::GetMap(const char* name, ProtoMap& map) const
			{
				ValueMap vmap;
				if (m_map.GetMap(name, vmap)){
					map.SetMap(vmap); return true;
				}
				return false;
			}

			bool ProtoMap::RefString(const char *name, const char *& value, size_t &size) const
			{
				return m_map.GetString(name, value, size);
			}

			bool ProtoMap::GetRaw(const char *name, Raw& value) const
			{
				return m_map.GetRaw(name, value);
			}

			//////////////////////////////////////////////////////////////////////////
			ProtoMessage::ProtoMessage(){}
			ProtoMessage::ProtoMessage(const ProtoMap& map)
			{
				Clear();
				const ValueMap& vmap = map;
				const Value& v = vmap.value();
				if (m_msg.decodeMap(v.start(), v.bytes, v.ptype == Value::VAR_MAP) < 0)
				{

				}
			}
			int ProtoMessage::decode(const char* buf, int len)
			{
				Clear();
				return m_msg.decode(buf, len);
			}
			void ProtoMessage::Clear()
			{
				m_msg.Clear();
			}
			int GetMapKeySize(const ProtoMap& cont,int level);
			int GetListKeySize(const ProtoList& cont, int level);

			int GetListKeySize(const ProtoList& cont, int level)
			{
				int keysum = 0;
				int index = 0;
				// list下面的map,第一个要忽略
				for (auto it = cont.begin(); it != cont.end(); ++it, ++index)
				{
					if (it->Type == Value::VAR_MAP)
					{
						const ProtoMap& msgmap = *it;
						if (index>0)
							keysum += GetMapKeySize(msgmap, level + 1);
					}
					else if (it->Type == Value::VAR_LIST)
					{
						const ProtoList& msglist = *it;
						keysum += GetListKeySize(msglist, level + 1);
					}
					else if (it->key)
					{
						keysum += it->keylen + 1;
					}
				}
				return keysum;
			}
			int GetMapKeySize(const ProtoMap& cont, int level)
			{
				int keysum = 0;
				for (auto it = cont.begin(); it != cont.end(); ++it)
				{
					if (it->Type == Value::VAR_MAP)
					{
						const ProtoMap& msgmap = *it;
						keysum += GetMapKeySize(msgmap, level+1);
					}
					else if (it->Type == Value::VAR_LIST)
					{
						const ProtoList& msglist = *it;
						keysum += GetListKeySize(msglist, level + 1);
					}
					else if (it->key)
					{
						keysum += it->keylen + 1;
					}
				}
				return keysum;
			}
			int ProtoMessage::GetAllKeySize()
			{
				ProtoMap pmap;
				pmap.SetMap(m_msg.MapValue());
				int keysum = 0;
				keysum=GetMapKeySize(pmap,0);
				return keysum;
			}
			namespace{
				std::string GetPattern(const ProtoList& cont);
				std::string GetPattern(const ProtoMap& cont);
				std::string GetPattern(const ProtoMap& cont)
				{
					auto it = cont.begin();
					if (!(it != cont.end()))
						return "map:{}";
					bool allTypeEqual = true;
					uint8_t fistType = it->Type;
					std::string pattern = "";
					int index = 0;
					for (; it != cont.end(); ++it)
					{
						if (it->Type != fistType)
							allTypeEqual = false;
					}
					for (it = cont.begin(); it != cont.end(); ++it, ++index)
					{

						if (index > 0)
							pattern += ",";
						if (it->key && it->keylen>0)
							pattern += std::string(it->key, it->keylen);
						else
							pattern += std::string("null");
						if (allTypeEqual)
							continue;
						if (it->Type == Value::VAR_MAP)
						{
							const ProtoMap& msgmap = *it;
							pattern += std::string(":") + GetPattern(msgmap);

						}
						else if (it->Type == Value::VAR_LIST)
						{
							const ProtoList& msglist = *it;
							pattern += std::string(":") + GetPattern(msglist);
						}
					}
					return pattern;
				}
				std::string GetPattern(const ProtoList& cont)
				{
					auto it = cont.begin();
					if (!(it != cont.end()))
						return "list:{}";
					bool allTypeEqual = true;
					uint8_t fistType = it->Type;
					cont.size();
					for (; it != cont.end(); ++it)
					{
						if (it->Type != fistType)
							return "list:{...}";
						if (it->Type == Value::VAR_MAP)
						{
							const ProtoMap& msgmap = *it;
							char buf[1024] = { 0 };
							sprintf(buf, "records:%d{%s}", cont.size(), GetPattern(msgmap).c_str());
							return buf;
						}
						else if (it->Type == Value::VAR_LIST)
						{
							const ProtoList& msglist = *it;
							return "list:" + GetPattern(msglist);
						}
						else
						{
							return "list:{v}";
						}
					}
					return "list:{}";
				}
				class JsonBuilder : public qb::base::JsonWriter{
					typedef unsigned int uint;
					typedef unsigned short ushort;
					struct PackHeader{						// 更新包中的数据头部
						uint	tag;						// 文件开头的4个字节,0x44425253
						uint	StartPos;					// 记录开始的偏移量
						uint	RecordCount;				// 记录个数
						ushort	FieldCount;					// 每条记录的字段个数
					};
					/*
					QB收到的字典数据包中的数据类型编码,目前只用到int32,string,double,time32四种类型
					*/
					enum kPackDateType{
						kPackDateTypeNone = 0,
						kPackDateTypeInt8 = 1,
						kPackDateTypeUInt8 = 2,
						kPackDateTypeInt16 = 3,
						kPackDateTypeUInt16 = 4,
						kPackDateTypeInt32 = 5,
						kPackDateTypeUint32 = 6,
						kPackDateTypeInt64 = 7,
						kPackDateTypeUInt64 = 8,
						kPackDateTypeBool = 9,
						kPackDateTypeString = 10,
						kPackDateTypeFloat = 11,
						kPackDateTypeDouble = 12,
						kPackDateTypeRaw = 13,
						kPackDateTypeTime32 = 14,	//等同于time_t，精度秒
						kPackDateTypeTime64 = 15,	//等同于time_t + 毫秒，精度毫秒
						kPackDateTypeCount = 16
					};
				public:
					typedef qb::base::JsonWriter JsonWriter;
					typedef qb::base::JsonWriter::JsonWriterMap WMap;
					typedef qb::base::JsonWriter::JsonWriterList WList;
				protected:
					JsonWriter m_writer;
					IRawParser*	m_rawParser;
				public:
					JsonBuilder(IRawParser* rawParser=nullptr) :m_rawParser(rawParser){}
					void AddValueList(WList& parent, const ValueList& vmap)
					{
						for (auto it = vmap.begin(); it != vmap.end(); ++it)
						{
							if (it->Type == Value::VAR_MAP)
							{
								const ValueMap& msgmap = *it;
								WMap node = parent.AddMap();
								AddValueMap(node, msgmap);
							}
							else if (it->Type == Value::VAR_LIST)
							{
								const ValueList& msglist = *it;
								WList node = parent.AddList();
								AddValueList(node, msglist);
							}
							else {
								AddValue(parent, *it);
							}
						}
					}
					void AddValueMap(WMap& parent, const ValueList& vmap)
					{
						for (auto it = vmap.begin(); it != vmap.end(); ++it)
						{
							if (it->Type == Value::VAR_MAP)
							{
								const ProtoMap& msgmap = *it;
								WMap node = parent.AddMap(std::string(it->key, it->keylen).c_str());
								AddValueMap(node, msgmap);
							}
							else if (it->Type == Value::VAR_LIST)
							{
								const ValueList& msglist = *it;
								WList node = parent.AddList(std::string(it->key, it->keylen).c_str());
								AddValueList(node, msglist);
							}
							else {
								AddValue(parent, *it);
							}
						}
					}
					bool IsValidDict(const PackHeader& head, const char* start,int nfield)
					{
						int typelens[kPackDateTypeCount] = { 0, 0, 0, 0, 0,
							sizeof(int), 0, 0, 0, 0,
							1, 0, sizeof(double), 0, sizeof(time_t), 0
						};// 各个类型的数据长度,参见_SkipBuffer
						const char* record_start = start;
						for (int i = 0; i < (int)head.RecordCount; i++)
						{
							const char* record = record_start;
							int ignore_col_count = 0;
							for (int j = 0; j < (int)head.FieldCount; j++)
							{
								kPackDateType type = (kPackDateType)(*record);
								char gap = record[1];//类型之后的一个字节
								const char* data = record + 2;	// 变长的数据开始,长度由类型和内容决定
								if (gap != 0)
								{
									//LOGWARN("ignore col:%d", j);
									record = record + 2;
									ignore_col_count++;
									continue;
								}
								int len = 2 + typelens[type];
								int dlen = (type == kPackDateTypeString) ? strlen(data) : 0;
								len += dlen;
								if (j >= nfield)	// 此字段QB没有,忽略
								{
									record = record + len;
									continue;
								}
								switch (type)
								{
								case kPackDateTypeInt32:
								case kPackDateTypeTime32:
								case kPackDateTypeDouble:
								case kPackDateTypeString:
									break;
								default:
									return false; break;
								}
								record = record + len;
							}
							record_start = record + 8;//两条记录之间间隔8字节
						}
						return true;
					}
					bool AddRaw(WMap& parent, const std::string& key, const char* sBuffer, int length)
					{
						// 首先,判断raw数据是否是字典格式
						// 如果不是,那么parent.AddString(key, "#raw");
						ValueDict dict;
						if (dict.Parse(sBuffer, length))
						{
							int row = dict.GetRowCount();
							int col = dict.GetColCount();
							ValueDict::Field value;
							time_t t = 0;
							WList wlist = parent.AddList(key.c_str());
							for (int i = 0; i < row;i++)
							{
								WMap wmap = wlist.AddMap();
								for (int j = 0; j < col; j++)
								{
									if(!dict.GetValue(i, j, value) || value.data==nullptr)
										continue;
									switch (value.type)
									{
									case 5:wmap.AddInt(value.name, *(int*)value.data); break;
									case 14:
										t = *(time_t*)value.data;
										if (sizeof(time_t) == sizeof(int))
											wmap.AddInt(value.name, t);
										else
											wmap.AddInt64(value.name, t);
										break;
									case 12:wmap.AddDouble(value.name, *(double*)value.data); break;
									case 10:wmap.AddString(value.name, (const char*)value.data, value.len); break;
									default:break;
									}
								}
							}
							return true;
						}

						/*
							外部可以在调用ProtoMessage::ToJson的时候,提供
							一个实现了IRawParser的解码器
							比如解析table格式的解码器,作为额外的第二个参数
							如果顺利解析,将会在原始json中增加解析后的消息
						*/
						if (m_rawParser && m_rawParser->Parse(sBuffer, length))
						{
							typedef IRawParser::kExpectType kExpectType;
							WList wlist = parent.AddList(key.c_str());
							int row = m_rawParser->GetRow();
							int col = m_rawParser->GetCol();
							double dvalue = 0;
							long long ivalue = 0;
							const long long i32max = ((long long)1UL) << 31;
							const long long u32max = ((long long)1UL) << 32;
							for (int i = 0; i < row;i++)
							{
								WMap wmap = wlist.AddMap();
								for (int k = 0; k < col;k++)
								{
									if(m_rawParser->IsCellDefault(i,k))
										continue;
									kExpectType type = m_rawParser->GetColType(k);
									const char* name = m_rawParser->GetColName(k);
									switch (type)
									{
									case IRawParser::kExpectTypeInt:
										m_rawParser->GetCellValue(i, k, ivalue);
										if (ivalue<i32max)
											wmap.AddInt(name,(int)ivalue);
										else if (ivalue<u32max)
											wmap.AddUint(name, (unsigned int)ivalue);
										else
											wmap.AddInt64(name,ivalue);
										break;
									case IRawParser::kExpectTypeDouble:
										m_rawParser->GetCellValue(i, k, dvalue);
										wmap.AddDouble(name, dvalue);
										break;
									case IRawParser::kExpectTypeString:
									{
										int len = 0;
										const char* str = nullptr;
										m_rawParser->GetCellValue(i, k, str, len);
										wmap.AddString(name, str, len);
									}
									break;
									default:
										break;
									}
								}
							}
							return true;
						}
						return false;
						//static char buf[Y_RD_SERVICE_MESSAGE_BLOCK_LEN] = { 0 };
						//int size = 0;
						//if (!bUnZip((char*)sBuffer, length, buf, &size))
						//	return false;

						//PackHeader head = *((PackHeader*)buf);
						//vector<const char*> fields; fields.reserve(head.FieldCount);
						//int pack_headsize = FIELD_OFFSET(PackHeader, FieldCount) + RTL_FIELD_SIZE(PackHeader, FieldCount);
						//const char* field_start = buf + pack_headsize;
						//if (size <= pack_headsize)
						//	return false;
						//if (head.tag != 0x53524244)
						//	return false;
						//if (head.FieldCount > 1000)
						//	return false;
						//for (int i = 0; i < head.FieldCount; i++)
						//{
						//	fields.push_back(field_start);
						//	field_start += strlen(field_start) + 2;
						//}
						//int nfield = fields.size();
						//const char* record_start = buf + head.StartPos + 8;
						//if (record_start - buf >= size)
						//	return false;
						//int typelens[kPackDateTypeCount] = { 0, 0, 0, 0, 0,
						//	sizeof(int), 0, 0, 0, 0,
						//	1, 0, sizeof(double), 0, sizeof(time_t), 0
						//};// 各个类型的数据长度,参见_SkipBuffer
						//if (!IsValidDict(head, record_start, nfield))
						//	return false;
						//time_t t = 0;
						//WList wlist = parent.AddList(key.c_str());
						//for (int i = 0; i < (int)head.RecordCount; i++)
						//{
						//	const char* record = record_start;
						//	int ignore_col_count = 0;
						//	WMap wmap = wlist.AddMap();
						//	for (int j = 0; j < (int)head.FieldCount; j++)
						//	{
						//		kPackDateType type = (kPackDateType)(*record);
						//		char gap = record[1];//类型之后的一个字节
						//		const char* data = record + 2;	// 变长的数据开始,长度由类型和内容决定
						//		if (gap != 0)
						//		{
						//			//LOGWARN("ignore col:%d", j);
						//			record = record + 2;
						//			ignore_col_count++;
						//			continue;
						//		}
						//		int len = 2 + typelens[type];
						//		int dlen = (type == kPackDateTypeString) ? strlen(data) : 0;
						//		len += dlen;
						//		if (j >= nfield )	// 此字段QB没有,忽略
						//		{
						//			record = record + len;
						//			continue;
						//		}
						//		switch (type)
						//		{
						//		case kPackDateTypeInt32:wmap.AddInt(fields[j],*(int*)data);break;
						//		case kPackDateTypeTime32:
						//			t = *(time_t*)data;
						//			if (sizeof(time_t)==sizeof(int))
						//				wmap.AddInt(fields[j], t);
						//			else
						//				wmap.AddInt64(fields[j], t);
						//			break;
						//		case kPackDateTypeDouble:wmap.AddDouble(fields[j], *(double*)data); break;
						//		case kPackDateTypeString:wmap.AddString(fields[j], (const char*)data,dlen); break;
						//		default:break;
						//		}
						//		record = record + len;
						//	}
						//	record_start = record + 8;//两条记录之间间隔8字节
						//}
						//return true;
					}
					void AddValue(WList& parent, const Value& v)
					{
						switch (v.Type)
						{
						case Value::VAR_VOID:break;
						case Value::VAR_BOOL:parent.AddBool(v); break;
						case Value::VAR_INT8:parent.AddInt(v); break;
						case Value::VAR_UINT8:parent.AddUint(v); break;
						case Value::VAR_INT16:parent.AddInt(v); break;
						case Value::VAR_UINT16:parent.AddUint(v); break;
						case Value::VAR_INT32:parent.AddInt(v); break;
						case Value::VAR_UINT32:parent.AddUint(v); break;
						case Value::VAR_INT64:parent.AddInt64(v); break;
						case Value::VAR_UINT64:parent.AddUint64(v); break;
						case Value::VAR_FLOAT:parent.AddDouble(v); break;
						case Value::VAR_DOUBLE:parent.AddDouble(v); break;
						case Value::VAR_STRING:
						{
							const char* str = nullptr;
							size_t len = 0;
							if (v.RefString(str, len))
								parent.AddString(str, len);
							else
								parent.AddString("");
						}break;
						case Value::VAR_RAW:
						{
							parent.AddString("#raw");
						}break;
						default:
							break;
						}
					}
					void AddValue(WMap& parent, const Value& v)
					{
						std::string key = v.GetKey();
						const char* k = key.c_str();
						switch (v.Type)
						{
						case Value::VAR_VOID:break;
						case Value::VAR_BOOL:parent.AddBool(k,(bool)v); break;
						case Value::VAR_INT8:parent.AddInt(k, (int8_t)v); break;
						case Value::VAR_UINT8:parent.AddUint(k, (uint8_t)v); break;
						case Value::VAR_INT16:parent.AddInt(k, (int16_t)v); break;
						case Value::VAR_UINT16:parent.AddUint(k, (uint16_t)v); break;
						case Value::VAR_INT32:parent.AddInt(k, (int32_t)v); break;
						case Value::VAR_UINT32:parent.AddUint(k, (uint32_t)v); break;
						case Value::VAR_INT64:parent.AddInt64(k, (int64_t)v); break;
						case Value::VAR_UINT64:parent.AddUint64(k, (uint64_t)v); break;
						case Value::VAR_FLOAT:parent.AddDouble(k, (float)v); break;
						case Value::VAR_DOUBLE:parent.AddDouble(k,(double)v); break;
						case Value::VAR_STRING:
						{
							const char* str = nullptr;
							size_t len = 0;
							if (v.RefString(str, len) && len>0)
								parent.AddString(k, str, len);
							else
								parent.AddString(k, "");
						}break;
						case Value::VAR_RAW:
						{
							if(!AddRaw(parent,key, v.data, v.size))
								parent.AddString(key.c_str(), "#raw");
						}break;
						default:
							break;
						}
					}
				};
			}

			int ProtoMessage::ToJson(std::string& str)
			{
				return ToJson(str, nullptr);
			}
			int ProtoMessage::ToJson(std::string& str, IRawParser* rawParser)
			{
				JsonBuilder builder(rawParser);
				builder.SetFormat();
				JsonBuilder::WMap root = builder.AddRootMap();
				{
					JsonBuilder::WMap jhead = root.AddMap("head");
					builder.AddValueMap(jhead, m_msg.Header());
				}
				{
					JsonBuilder::WMap jbody = root.AddMap("body");
					builder.AddValueMap(jbody, m_msg.MapValue());
				}
				root.End();
				str = builder.c_str();
				return str.size();
			}

			void ProtoMessage::Dump(int fid)
			{
				int keysum = GetAllKeySize();
				int total = m_msg.Header().value().bytes +
					m_msg.MapValue().value().bytes;
				ProtoMap pmap;
				pmap.SetMap(m_msg.MapValue());
				std::string pattern = GetPattern(pmap);

				// 将所有消息先保存到本地
				if (0)
				{
				/*	static int id = 0;
					char fname[MAX_PATH] = { 0 };
					SYSTEMTIME st;
					GetLocalTime(&st);
					sprintf(fname, "./data/msg/%05d_%08d_%05d_%08d_%02d%02d%02d_%03d.msg",
						GetCurrentProcessId(), id++, fid, total,
						st.wHour, st.wMinute, st.wSecond, st.wMilliseconds
						);
					const char* fdata = m_msg.Header().value().parent.data;
					StringUtil::SaveFileContent(fdata, total, fname);*/ //syy
				}


				if (pattern.size() > 1024)
				{
					pattern = pattern.substr(0, 1024);
				}
				else
				{
				}
				
			}
			bool ProtoMessage::GetList(const char* name, ProtoList& list) const
			{
				ValueList v;
				if (m_msg.MapValue().GetList(name, v))
				{
					list.SetList(v);
					return true;
				}
				return false;
			}
			std::string ProtoMessage::GetType()const{
				const char* value = nullptr;
				size_t size = 0;
				if (m_msg.Header().GetString(PropType.c_str(), value, size) && value)
					return std::string(value, size);
				return "";
			}
			std::string ProtoMessage::getType()const{ return GetType(); }
			std::string ProtoMessage::GetMessageID()const{
				const char* value = nullptr;
				size_t size = 0;
				if (m_msg.Header().GetString(PropMessageID.c_str(), value, size) && value)
					return std::string(value, size);
				return "";
			}
			std::string ProtoMessage::getMessageID()const{
				return GetMessageID();
			}
			std::string ProtoMessage::GetSubject()const{
				const char* value = nullptr;
				size_t size = 0;
				if (m_msg.Header().GetString(PropSubject.c_str(), value, size) && value)
					return std::string(value, size);
				return "";
			}
			std::string ProtoMessage::getSubject()const{
				return GetSubject();
			}

			//////////////////////////////////////////////////////////////////////////
			void ValueList::print(int level)const
			{
				for (const_iterator it = begin(); it != end(); ++it)
				{
					const Value& v = *it;
					if (v.Type == Value::VAR_LIST)
					{
						ValueList vlist(v);
						vlist.print(level + 1);
					}
					else if (v.Type == Value::VAR_MAP)
					{
						ValueMap vmap(v);
						vmap.print(level + 1);
					}
					else
						printf("\n%4d:%4d\t:  %s", it.size(), it.index(), v.tostring().c_str());
				}
			}
			void Message::print()const
			{
				m_header.print();
				m_map.print();
			}
		}
	}//namespace base;
}//namespace qb;
